﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Data;
using System.Text;
using System.IO;
using YiYiTong.Rocket.Helper;
using YiYiTong.Rocket.Entity;
using YiYiTong.Rocket.Model;
using YiYiTong.Rocket.DataAccess;
using YiYiTong.Rocket.EFDBFirst;
using YiYiTong.Rocket.Business.Biz;
using YiYiTong.Rocket.Business.Third;

namespace YiYiTong.Rocket.Business
{
    public class AccountBiz
    {
        #region 单例模式
        private AccountBiz()
        {
        }

        private static AccountBiz _instance;
        private static readonly object _syncObject = new object();

        public static AccountBiz Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_syncObject)
                    {
                        if (_instance == null)
                        {
                            _instance = new AccountBiz();
                        }
                    }
                }
                return _instance;
            }
        }
        #endregion 单例模式

        #region 登录相关
        /// <summary>
        /// 用户登录
        /// </summary>
        /// <returns></returns>
        public Tuple<bool, AccLoginModel, string> Login(string mobile, string code, string machineCode)
        {
            return DoLogin(mobile, code, (int)SendType.LoginCode, "", "", machineCode);
        }

        /// <summary>
        /// 微信登录
        /// </summary>
        /// <returns></returns>
        public Tuple<bool, WxAccLoginModel, string> WxLogin(string code, string machineCode)
        {
            string open_id = string.Empty;
            string accessToken = string.Empty;
            //1.请求微信授权
            string wxTokenKey = string.Format("wechat-token-{0}", code);
            //refresh_token拥有较长的有效期（30天）且无法续期，当refresh_token失效的后，需要用户重新授权
            string wxRefreshTokenKey = string.Format("wechat-refresh-token-{0}", code);
            string refreshToken = RedisService.Get<string>(wxRefreshTokenKey);
            if (string.IsNullOrEmpty(refreshToken))
            {
                //登录授权
                var result = WechatOauthBiz.GetAccessToken(code);
                if (result.Item1)
                {
                    open_id = result.Item2.openid;
                    accessToken = result.Item2.access_token;
                    RedisService.Set(wxTokenKey, JsonHelper.Serialize(result.Item2), DateTime.Now.AddSeconds(result.Item2.expires_in));
                    RedisService.Set(wxRefreshTokenKey, result.Item2.refresh_token, DateTime.Now.AddDays(30));
                }
                else
                    return new Tuple<bool, WxAccLoginModel, string>(false, null, "微信登录授权失败");
            }
            else
            {
                //刷新或续期access_token使用
                var result1 = WechatOauthBiz.RefreshToken(refreshToken);
                if (result1.Item1)
                {
                    open_id = result1.Item2.openid;
                    accessToken = result1.Item2.access_token;
                    RedisService.Set(wxTokenKey, JsonHelper.Serialize(result1.Item2), DateTime.Now.AddSeconds(result1.Item2.expires_in));
                    RedisService.Set(wxRefreshTokenKey, result1.Item2.refresh_token, DateTime.Now.AddDays(30));

                }
                else
                    return new Tuple<bool, WxAccLoginModel, string>(false, null, "微信登录授权失败");
            }

            WxAccLoginModel model = new WxAccLoginModel();
            model.isFirstLogin = 0;
            //2.通过微信授权id查询账号信息
            AccountInfo info = AccountDataAccess.Instance.GetAccountByWx((int)LogonType.Wechat, open_id);
            if (info == null)
            {
                //用户首次微信授权登录
                model.accessToken = accessToken;
                model.openId = open_id;
                model.isFirstLogin = 1;
                return new Tuple<bool, WxAccLoginModel, string>(true, model, "");
            }
            else
            {
                //增加用户状态判断
                if (info.account_status != (short)AccountStatus.Normal)
                    return new Tuple<bool, WxAccLoginModel, string>(false, null, "用户异常");

                int issetpaypwd = 0;
                if (!string.IsNullOrWhiteSpace(info.pay_password))
                    issetpaypwd = 1;

                //设置登录token对象
                UserTokenModel tokenModel = new UserTokenModel();
                tokenModel.UserId = info.uid;
                tokenModel.UserName = info.member_name;
                tokenModel.UserNick = info.member_name;
                tokenModel.Mobile = info.account_mobile;
                tokenModel.ExpiredTime = DateTime.Now.AddDays(ConfigHelper.AppSetting<int>("TokenValid", 1));
                tokenModel.MachineCode = machineCode;
                tokenModel.Token = OAuthBiz.Instance.CreateToken(tokenModel);


                model.uid = info.uid;
                model.membername = info.member_name;
                model.memberlevel = info.member_level;
                model.mobile = info.account_mobile;
                model.issetpaypwd = issetpaypwd;
                model.token = tokenModel.Token;
                model.levelList = GetMemberLevel(info.member_level);

                ADZ_MasterEntities dbcontext = new ADZ_MasterEntities();
                if (dbcontext.ADZ_MemberFollow.FirstOrDefault(t => t.uid == info.uid) != null)
                {
                    model.isfollowed = 1;
                }
                else
                {
                    model.isfollowed = 0;
                }

                //3.登录token存入缓存中
                if (OAuthBiz.Instance.SetUserInfo(tokenModel))
                {
                    //记录登录日志
                    AddLogonLog(info.uid, (short)LogonType.Wechat, tokenModel.Token, machineCode, Utils.GetClientIP());
                    return new Tuple<bool, WxAccLoginModel, string>(true, model, "");
                }
                else
                {
                    LogHelper.Error("用户登录,token存入缓存失败");
                    return new Tuple<bool, WxAccLoginModel, string>(false, null, "微信登录授权失败");
                }
            }
        }

        /// <summary>
        /// 账号绑定
        /// </summary>
        public Tuple<bool, AccLoginModel, string> Bind(string mobile, string code, string openid, string accesstoken, string machineCode)
        {
            return DoLogin(mobile, code, (int)SendType.BindCode, openid, accesstoken, machineCode);
        }

        /// <summary>
        /// 退出登录
        /// </summary>
        /// <param name="mobile"></param>
        public bool LoginOut(long uid, string machineCode = "")
        {
            //取消推送设备绑定
            PushMsgDataAccess.Instance.DelMemberPushBind(uid);

            return OAuthBiz.Instance.RemoveToken(uid, machineCode);
        }

        //统一登录方法
        private Tuple<bool, AccLoginModel, string> DoLogin(string mobile, string code, int sendType, string openid, string accesstoken, string machineCode)
        {
            bool isLogin = false;
            //是否需要注册账号
            bool isRegAcc = false;
            bool isEditAcc = false;
            string headurl = string.Empty;

            long uid = 0;
            int sex = 0;  //性别 0 默认 1 男 2 女
            string userName = "";
            short memberlevel = 0;
            int issetpaypwd = 0;

            //1.验证库中手机号是否注册
            AccountInfo info = AccountDataAccess.Instance.GetAccount(mobile);
            if (info == null)
                isRegAcc = true;
            else
            {
                uid = info.uid;
                userName = info.member_name;
                memberlevel = info.member_level;
                if (!string.IsNullOrWhiteSpace(info.pay_password))
                    issetpaypwd = 1;

                //验证用户状态
                if (info.account_status != (short)AccountStatus.Normal)
                {
                    LogHelper.Error("用户禁止登录");
                    return new Tuple<bool, AccLoginModel, string>(isLogin, null, "用户异常");
                }
            }

            if ((!string.IsNullOrEmpty(openid) && !string.IsNullOrEmpty(accesstoken)))
            {
                //微信号只能绑定一个会员账户,反之亦然
                var wxAcc = AccountDataAccess.Instance.GetAccountByWx((int)LogonType.Wechat, openid);
                if (wxAcc != null)
                    return new Tuple<bool, AccLoginModel, string>(isLogin, null, "微信号只能绑定一个会员账户");

                //请求微信，获取微信用户信息
                var tupleWxUser = WechatOauthBiz.GetUser(accesstoken, openid);
                if (tupleWxUser.Item1)
                {
                    isEditAcc = true;
                    userName = tupleWxUser.Item2.nickname;
                    sex = tupleWxUser.Item2.sex;
                    headurl = tupleWxUser.Item2.headimgurl;
                }
            }

            //处理头像
            if (string.IsNullOrEmpty(headurl))
            {
                headurl = GetHeadUrl(sex);
            }

            //2.验证手机验证码
            var result = CheckCode(mobile, code, sendType);
            if (!result.Item1)
                return new Tuple<bool, AccLoginModel, string>(isLogin, null, result.Item2);

            string stroutput = string.Empty;
            short logonType = (short)LogonType.VaildCode;
            if (sendType == (int)SendType.BindCode)
            {
                logonType = (short)LogonType.Wechat;
            }

            //3.登录成功后，没有账户则注册账户
            if (isRegAcc)
            {
                if (RegisterAcc(mobile, userName, headurl, openid, logonType, sex, out uid, out memberlevel, out stroutput))
                {
                    userName = stroutput;
                    isLogin = true;
                }
                else
                {
                    LogHelper.Error("用户登录,注册账户失败");
                    return new Tuple<bool, AccLoginModel, string>(isLogin, null, "注册账户失败");
                }
            }
            else
            {
                if (isEditAcc)
                    EditAcc(uid, userName, headurl, logonType, openid);
            }

            //设置登录token对象
            UserTokenModel tokenModel = new UserTokenModel();
            tokenModel.UserId = uid;
            tokenModel.UserName = userName;
            tokenModel.UserNick = userName;
            tokenModel.Mobile = mobile;
            tokenModel.ExpiredTime = DateTime.Now.AddDays(ConfigHelper.AppSetting<int>("TokenValid", 1));
            tokenModel.MachineCode = machineCode;
            tokenModel.Token = OAuthBiz.Instance.CreateToken(tokenModel);

            AccLoginModel model = new AccLoginModel();
            model.uid = uid;
            model.membername = userName;
            model.memberlevel = memberlevel;
            model.mobile = mobile;
            model.issetpaypwd = issetpaypwd;
            model.token = tokenModel.Token;
            model.levelList = GetMemberLevel(memberlevel);

            ADZ_MasterEntities dbcontext = new ADZ_MasterEntities();
            if (dbcontext.ADZ_MemberFollow.FirstOrDefault(t => t.uid == uid) != null)
            {
                model.isfollowed = 1;
            }
            else
            {
                model.isfollowed = 0;
            }
            //4.登录token存入缓存中
            if (OAuthBiz.Instance.SetUserInfo(tokenModel))
            {
                isLogin = true;
                //记录登录日志
                AddLogonLog(uid, logonType, tokenModel.Token, machineCode, Utils.GetClientIP());
                return new Tuple<bool, AccLoginModel, string>(isLogin, model, "");
            }
            else
            {
                LogHelper.Error("用户登录,token存入缓存失败");
                return new Tuple<bool, AccLoginModel, string>(isLogin, null, "登录失败");
            }
        }

        /// <summary>
        /// 记录登录日志
        /// </summary>
        /// <returns></returns>
        public void AddLogonLog(long uid, short logonType, string logonToken, string logonDeviceNo, string logonIp)
        {
            string str = string.Empty;
            string nation = string.Empty;
            string province = string.Empty;
            string city = string.Empty;
            string district = string.Empty;
            if (!string.IsNullOrEmpty(logonIp) && !logonIp.Equals("::1") && !logonIp.Equals("127.0.0.1") && !logonIp.StartsWith("192.168"))
            {

                string ip = logonIp.Substring(0, logonIp.LastIndexOf('.'));
                ADZ_MasterEntities dbcontext = new ADZ_MasterEntities();
                var query = dbcontext.ADZ_IpCity.FirstOrDefault(t => t.Ip.StartsWith(logonIp));
                if (query != null)
                {
                    nation = query.Nation;
                    province = query.Province;
                    city = query.City;
                    district = query.District;
                }
                else
                {
                    //库中没有通过接口查询
                    var result = IpBiz.GetCityByIp(logonIp);
                    if (result.Item1)
                    {
                        nation = result.Item2.nation;
                        province = result.Item2.province;
                        city = result.Item2.city;
                        district = result.Item2.district;

                        //计入本地数据库
                        ADZ_IpCity model = new ADZ_IpCity();
                        model.City = city;
                        model.District = district;
                        model.Ip = logonIp;
                        model.Nation = nation;
                        model.Province = province;
                        model.CreateTime = DateTime.Now;
                        dbcontext.ADZ_IpCity.Add(model);
                        dbcontext.SaveChanges();

                    }
                }
            }
            AccountDataAccess.Instance.AddLogonLog(uid, logonType, logonToken, logonDeviceNo, logonIp, nation, province, city, district, out str);
        }
        /// <summary>
        /// 修改用户信息
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="membername"></param>
        /// <param name="headurl"></param>
        /// <param name="logonType"></param>
        /// <param name="openId"></param>
        /// <returns></returns>
        public bool EditAcc(long uid, string membername, string headurl, short logonType, string openId)
        {
            if (uid <= 0 || string.IsNullOrWhiteSpace(membername) || string.IsNullOrWhiteSpace(headurl) || string.IsNullOrWhiteSpace(openId))
                return false;

            //修改账户主表信息
            ADZ_MasterEntities dbcontext = new ADZ_MasterEntities();
            var acc = dbcontext.ADZ_MemberMaster.FirstOrDefault(t => t.uid == uid && t.is_del == 0);
            if (acc == null)
                return false;

            acc.member_name = membername;
            acc.logo_img_url = headurl;
            dbcontext.SaveChanges();

            //修改账户从表信息
            var entity = dbcontext.ADZ_OpenReg.FirstOrDefault(t => t.uid == uid && t.logon_type == logonType);
            if (entity != null)
            {
                entity.open_key = openId;
                dbcontext.SaveChanges();
            }
            else
            {
                ADZ_OpenReg openReg = new ADZ_OpenReg();
                openReg.logon_type = (byte)logonType;
                openReg.uid = uid;
                openReg.open_key = openId;
                openReg.create_time = DateTime.Now;

                dbcontext.ADZ_OpenReg.Add(openReg);
                dbcontext.SaveChanges();
            }
            return true;
        }

        /// <summary>
        /// 验证码检查
        /// </summary>
        /// <param name="mobile"></param>
        /// <param name="code"></param>
        /// <param name="sendType"></param>
        /// <returns></returns>
        public Tuple<bool, string> CheckCode(string mobile, string code, int sendType)
        {
            string codeErrorKey = string.Format("code-error-{0}-{1}", mobile, sendType);    //手机登录验证码错误次数
            int errorNum = RedisService.Get<int>(codeErrorKey);
            if (errorNum == 4)
            {
                //验证码错误5次，防止用户刷验证码
                LogHelper.Error("验证码已错误5次");
                return new Tuple<bool, string>(false, "验证码错误次数过多");
            }

            string codeKey = string.Format("code-{0}-{1}", mobile, sendType);
            string saveCode = RedisService.Get<string>(codeKey);    //缓存中保存的验证码
            if (string.IsNullOrEmpty(saveCode))
            {
                //验证码已失效
                LogHelper.Error("验证码已失效");
                return new Tuple<bool, string>(false, "验证码已失效");
            }
            if (code != saveCode)
            {
                //验证码错误
                if (errorNum == 0)
                    RedisService.Set(codeErrorKey, 1, DateTime.Now.AddMinutes(5));
                else
                    RedisService.Set(codeErrorKey, errorNum + 1, DateTime.Now.AddMinutes(5));
                return new Tuple<bool, string>(false, "验证码错误");
            }
            return new Tuple<bool, string>(true, "");
        }

        public List<MemberLevelModel> GetMemberLevel(int currentMemberLevel)
        {
            List<MemberLevelModel> list = new List<MemberLevelModel>();
            //获取高于自己用户等级的等级配置 leev 2019-04-04
            ADZ_MasterEntities dbcontext = new ADZ_MasterEntities();
            var levelconfigList = dbcontext.ADZ_MemberLevelConfig.Where(t => t.member_level > currentMemberLevel).ToList();
            if (levelconfigList != null)
            {
                foreach (var item in levelconfigList)
                {
                    MemberLevelModel model = new MemberLevelModel();
                    model.member_level = item.member_level;
                    model.member_name = item.member_name;
                    model.add_rate = (decimal)item.add_rate;
                    list.Add(model);
                }
            }
            return list;
        }
        #endregion

        #region 账户相关
        /// <summary>
        /// 编辑基本信息
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="real_name"></param>
        /// <param name="sex"></param>
        /// <param name="company_name"></param>
        /// <param name="address"></param>
        /// <param name="id_number"></param>
        /// <param name="contact_mobile"></param>
        /// <param name="company_telephone"></param>
        /// <param name="company_address"></param>
        /// <returns></returns>
        public Tuple<bool, string> SaveDetails(long uid, string real_name, short sex, string company_name, string address,
            string id_number, string contact_mobile, string company_telephone, string company_address, int customer_type, string remark = "notset")
        {
            if (uid == 0 || !EnumHelper.IsDefined<SexEnum>((int)sex))
                return new Tuple<bool, string>(false, "参数有误");

            ADZ_MasterEntities dbcontext = new ADZ_MasterEntities();
            var member = dbcontext.ADZ_MemberMaster.FirstOrDefault(t => t.uid == uid && t.is_del == 0);
            if (member == null)
                return new Tuple<bool, string>(false, "会员信息有误");

            //更新sex性别
            member.sex = (byte)sex;
            dbcontext.SaveChanges();

            //更新从表开始
            var details = dbcontext.ADZ_MemberDetails.FirstOrDefault(t => t.uid == uid);
            if (details == null)
            {
                ADZ_MemberDetails addDetails = new ADZ_MemberDetails();
                addDetails.uid = uid;
                addDetails.id_number = id_number;
                addDetails.real_name = real_name;
                addDetails.create_time = DateTime.Now;
                addDetails.contact_mobile = contact_mobile;
                addDetails.company_telephone = company_telephone;
                addDetails.company_name = company_name;
                addDetails.company_address = company_address;
                addDetails.address = address;
                addDetails.customer_type = customer_type;
                addDetails.customer_type_name = EnumHelper.GetEnumItemDescription<customer_type>(customer_type);
                if (remark != "notset")
                    addDetails.remark = remark;
                dbcontext.ADZ_MemberDetails.Add(addDetails);
            }
            else
            {
                if (!string.IsNullOrEmpty(id_number))
                    details.id_number = id_number;
                if (!string.IsNullOrEmpty(company_telephone))
                    details.company_telephone = company_telephone;
                if (!string.IsNullOrEmpty(company_address))
                    details.company_address = company_address;
                details.address = address;
                details.real_name = real_name;
                details.company_name = company_name;
                details.contact_mobile = contact_mobile;
                details.customer_type = customer_type;
                if (remark != "notset")
                    details.remark = remark;
                details.customer_type_name = EnumHelper.GetEnumItemDescription<customer_type>(customer_type);
            }
            dbcontext.SaveChanges();
            return new Tuple<bool, string>(true, "");
        }

        /// <summary>
        /// 注册账号
        /// </summary>
        /// <returns></returns>
        public bool RegisterAcc(string mobile, string memberName, string headerUrl, string openid, short logontype,
            int sex, out long uid, out short memberlevel, out string stroutput)
        {
            bool flag = false;
            long ret = AccountDataAccess.Instance.RegisterAcc(mobile, memberName, headerUrl, openid, logontype, sex, out uid, out memberlevel, out stroutput);
            if (ret > 0)
            {
                memberName = stroutput;
                flag = true;
                //注册成功，发放注册奖励 by leev 2019-03-28
                decimal money = GetRegisterReward();
                if (money > 0)
                {
                    string pushMsg = string.Format("恭喜您成功注册为爱电子会员并获得{0}元注册奖励。", money);

                    long retUid = uid;
                    //加钱
                    AddAmt(retUid, mobile, money, OrderType.RewardRegister, pushMsg, "注册奖励");
                }

                BusinessMsgBiz.Instance.SendBusinessMsg(new ADZ_BusinessMsg
                {
                    BusinessMsgType = (int)BusinessMsgEnum.NewUser,
                    msg = $"用户{memberName}注册成功，手机号{mobile},获得奖励￥{money}",
                    msg_title = "新用户注册",
                    msg_url = $"/account/defailinfo?uid={uid}"
                });
            }

            return flag;
        }

































































































































































































































































































































        /// <summary>        /// 账户奖励加钱        /// </summary>        /// <returns></returns>        public bool AddAmt(long uid, string mobile, decimal money, OrderType orderType, string pushMsg, string pushTitle)
        {
            ADZ_MasterEntities dbcontext = new ADZ_MasterEntities();
            var chargeMember = dbcontext.ADZ_ChargeMaster.FirstOrDefault(t => t.uid == uid);
            if (chargeMember != null)
            {
                //加钱
                chargeMember.give_balance += money;
                chargeMember.account_balance += money;
                dbcontext.SaveChanges();

                //记录资金流水
                AddAmountLog(uid, money, (int)orderType, "", 0, pushTitle, pushTitle, 0);

                //发送短信
                SmsBiz.Instance.SendMessage(mobile, pushMsg);

                //发送推送消息
                AddPushMsgModel paramModel = new AddPushMsgModel
                {
                    aDZ_Pushmessage = new ADZ_Pushmessage
                    {
                        MsgType = 2,
                        ReceiveType = 1,
                        MsgTitle = pushTitle,
                        MsgText = pushMsg
                    },
                    ReceiveUids = uid.ToString()
                };
                PushMsgBiz.Instance.AddPushMsg(paramModel);
                return true;
            }
            return false;
        }

        /// <summary>
        /// 获取用户邀请码
        /// </summary>
        /// <param name="uid"></param>
        /// <returns></returns>
        public Tuple<bool, InviteCodeModel> GetInviteCode(long uid, int is_used, int pageIndex, int pageRows)
        {
            if (uid <= 0)
                return new Tuple<bool, InviteCodeModel>(false, null);

            DataSet ds = AccountDataAccess.Instance.GetInviteCode(uid, is_used, pageIndex, pageRows);
            if (ds != null && ds.Tables.Count > 0 && ds.Tables[1].Rows.Count > 0)
            {
                InviteCodeModel model = new InviteCodeModel();
                model.list = new ModelHandler<InviteCode>().FillModel(ds.Tables[1]);
                model.allrows = ConvertHelper.ConvertTo<int>(ds.Tables[0].Rows[0]["allrows"]);
                model.allpages = ConvertHelper.ConvertTo<int>(ds.Tables[0].Rows[0]["allpages"]);

                return new Tuple<bool, InviteCodeModel>(true, model);
            }
            else
                return new Tuple<bool, InviteCodeModel>(false, null);
        }

        /// <summary>
        /// 填写邀请码
        /// </summary>
        /// <param name="uid">被邀请人uid</param>
        /// <param name="code">邀请码</param>
        /// <returns></returns>
        public Tuple<bool, string> WriteInviteCode(long rel_uid, string code)
        {
            if (rel_uid <= 0)
                return new Tuple<bool, string>(false, "用户不存在");

            long uid = 0;
            string rel_mobile = string.Empty;
            string mobile = string.Empty;
            string stroutput = string.Empty;
            int ret = AccountDataAccess.Instance.WriteInviteCode(rel_uid, code, out uid, out mobile, out rel_mobile, out stroutput);
            if (ret > 0)
            {
                //邀请成功。邀请人发放现金奖励
                bool isReward = ConfigHelper.AppSetting<bool>("is_reward", false);
                if (isReward)
                {
                    decimal rewardAmt = ConfigHelper.AppSetting<decimal>("reward_amt", 0);
                    if (rewardAmt > 0)
                    {
                        //定义短信和推送消息内容
                        string pushMsg = string.Format("您成功邀请用户{0}加入爱电子，获得奖励{1}元，请查看爱电子余额。", rel_mobile, rewardAmt);

                        //加钱,推送信息和发短信通知
                        AddAmt(uid, mobile, rewardAmt, OrderType.RewardRecommend, pushMsg, "邀请奖励");
                    }
                }
                return new Tuple<bool, string>(true, "");
            }
            else
                return new Tuple<bool, string>(false, stroutput);
        }

        /// <summary>
        /// 绑定邀请码
        /// </summary>
        /// <param name="mobile">手机号</param>
        /// <param name="validCode">验证码</param>
        /// <param name="code">邀请码</param>
        /// <returns></returns>
        public Tuple<bool, string> BindInviteCode(string mobile, string validCode, string code)
        {
            //检查验证码是否正确
            var result = CheckCode(mobile, validCode, (int)SendType.RecommendCode);
            if (!result.Item1)
                return new Tuple<bool, string>(false, result.Item2);

            //判断验证码是否有效
            ADZ_MasterEntities dbcontext = new ADZ_MasterEntities();
            var inviteCode = dbcontext.ADZ_InviteCode.FirstOrDefault(t => t.invite_code == code);
            if (inviteCode == null)
                return new Tuple<bool, string>(false, "邀请码不存在");

            if (inviteCode.is_used != 0)
                return new Tuple<bool, string>(false, "邀请码已使用，不可重复填写");

            long uid = 0;
            var acc = AccountDataAccess.Instance.GetAccount(mobile);
            if (acc == null)
            {
                int sex = 0;  //性别 0 默认 1 男 2 女
                string userName = "";
                short memberlevel = 0;
                string headurl = GetHeadUrl(sex);
                string openid = "";
                string stroutput = string.Empty;
                short logonType = (short)LogonType.VaildCode;

                if (RegisterAcc(mobile, userName, headurl, openid, logonType, sex, out uid, out memberlevel, out stroutput))
                {
                    userName = stroutput;
                }
                else
                {
                    LogHelper.Error("用户登录失败");
                    return new Tuple<bool, string>(false, "注册账户失败");
                }
            }
            else
            {
                uid = acc.uid;
            }
            return WriteInviteCode(uid, code);
        }

        /// <summary>
        /// 生成邀请码
        /// </summary>
        /// <returns></returns>
        public Tuple<bool, string> BuildInviteCode(long uid)
        {
            ADZ_MasterEntities dbcontext = new ADZ_MasterEntities();
            if (uid > 0)
            {
                var member = dbcontext.View_Member.FirstOrDefault(t => t.uid == uid && t.is_del == 0);
                if (member == null)
                    return new Tuple<bool, string>(false, "会员不存在");

                if (member.invite_limit == 0)
                    return new Tuple<bool, string>(false, "没有生成邀请码权限");

                //已生成邀请码
                var codeCount = dbcontext.ADZ_InviteCode.Where(t => t.uid == uid).Count();
                if (codeCount >= member.invite_limit)
                    return new Tuple<bool, string>(false, "邀请码已达上限");

                var buildCount = member.invite_limit - codeCount;
                int exec_succ = 0;
                for (int i = 0; i < buildCount; i++)
                {
                    string code = Utils.GetRandomCode(6);
                    var is_exists = dbcontext.ADZ_InviteCode.Where(t => t.uid == uid && t.invite_code == code).Count() > 0;
                    //判断邀请码是否重复
                    if (is_exists)
                    {
                        buildCount = buildCount + 1;
                        continue;
                    }

                    string share_url = ConfigHelper.AppSetting<string>("shareUrl") + "?c=" + code + "&n=" + StringHelper.UrlEncode(member.member_name);
                    ADZ_InviteCode invitecode = new ADZ_InviteCode();
                    invitecode.uid = uid;
                    invitecode.share_url = share_url;
                    invitecode.is_used = 0;
                    invitecode.invite_code = code;
                    invitecode.create_time = DateTime.Now;

                    dbcontext.ADZ_InviteCode.Add(invitecode);
                    if (dbcontext.SaveChanges() > 0)
                        exec_succ++;
                }
                return new Tuple<bool, string>(true, string.Format("本次需生成邀请码{0}个，其中成功{1}个，失败{2}个", buildCount, exec_succ, (buildCount - exec_succ)));
            }
            else
                return new Tuple<bool, string>(false, "会员不存在");
        }

        /// <summary>
        /// 会员升级申请
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="contact_name">姓名</param>
        /// <param name="telephone">手机号</param>
        /// <param name="stroutput"></param>
        /// <returns></returns>
        public Tuple<bool, string> ApplyMemberUp(long uid, string contact_name, string telephone)
        {
            if (uid <= 0)
                return new Tuple<bool, string>(false, "用户不存在");

            ADZ_MasterEntities dbcontext = new ADZ_MasterEntities();
            ADZ_MemberUpApply apply = dbcontext.ADZ_MemberUpApply.FirstOrDefault(t => t.uid == uid && t.is_del == 0);
            if (apply != null)
            {
                //修改信息
                if (apply.is_do == 1)
                    return new Tuple<bool, string>(false, "您的申请已处理，请重新登录APP。");

                if (apply.is_do == 0)
                {
                    apply.contact_name = contact_name;
                    apply.contact_telephone = telephone;
                    apply.create_time = DateTime.Now;
                    dbcontext.SaveChanges();
                    return new Tuple<bool, string>(true, "");
                }

                apply.is_del = 1;
                dbcontext.SaveChanges();
            }

            string stroutput = string.Empty;
            long ret = AccountDataAccess.Instance.ApplyMemberUp(uid, contact_name, telephone, out stroutput);
            if (ret > 0)
            {
                //发送业务消息
                BusinessMsgBiz.Instance.SendBusinessMsg(new ADZ_BusinessMsg
                {
                    BusinessMsgType = (int)BusinessMsgEnum.UserApplyDegree,
                    msg = $"用户申请提升会员等级为共生会员，手机号{telephone}",
                    msg_title = "用户申请提升会员等级",
                    msg_url = $"/account/memberupapplylist"
                });
                return new Tuple<bool, string>(true, "");
            }
            else
                return new Tuple<bool, string>(false, stroutput);

        }

        /// <summary>
        /// 获取会员升级申请
        /// </summary>
        /// <returns></returns>
        public Tuple<bool, ADZ_MemberUpApply> GetMemberApplyUp(long uid)
        {
            if (uid > 0)
            {
                ADZ_MasterEntities dbcontext = new ADZ_MasterEntities();
                ADZ_MemberUpApply apply = dbcontext.ADZ_MemberUpApply.OrderByDescending(t => t.seq_id).FirstOrDefault(t => t.uid == uid && t.is_del == 0);
                if (apply != null)
                    return new Tuple<bool, ADZ_MemberUpApply>(true, apply);
                else
                    return new Tuple<bool, ADZ_MemberUpApply>(false, null);
            }
            return new Tuple<bool, ADZ_MemberUpApply>(false, null);
        }
        /// <summary>
        /// 记录资金流水
        /// </summary>
        /// <returns></returns>
        public bool AddAmountLog(long uid, decimal amt, int ordertype, string orderid, int inorout, string message, string remark, int is_show)
        {
            if (AccountDataAccess.Instance.AddAmountLog(uid, amt, ordertype, orderid, inorout, message, remark, is_show) > 0)
                return true;
            else
                return false;
        }
        /// <summary>
        /// 申请卖家
        /// </summary>
        /// <returns></returns>
        public Tuple<bool, string> ApplySeller(long uid, string company_name, string contact_name, string telephone, string sex, string email, string qq, string company_address)
        {
            if (uid <= 0)
                return new Tuple<bool, string>(false, "用户不存在");

            ADZ_MasterEntities dbcontext = new ADZ_MasterEntities();
            ADZ_SellerApply seller = dbcontext.ADZ_SellerApply.FirstOrDefault(t => t.uid == uid);
            if (seller != null)
            {
                //修改信息
                if (seller.is_do == 1)
                    return new Tuple<bool, string>(false, "申请已处理");

                seller.company_address = company_address;
                seller.company_name = company_name;
                seller.contact_name = contact_name;
                seller.email = email;
                seller.qq = qq;
                seller.sex = sex;
                seller.telephone = telephone;
                dbcontext.SaveChanges();

                return new Tuple<bool, string>(true, "");
            }
            else
            {
                string stroutput = string.Empty;
                long ret = AccountDataAccess.Instance.ApplySeller(uid, company_name, contact_name, telephone, sex, email, qq, company_address, out stroutput);
                if (ret > 0)
                {
                    //发送业务消息
                    BusinessMsgBiz.Instance.SendBusinessMsg(new ADZ_BusinessMsg
                    {
                        BusinessMsgType = (int)BusinessMsgEnum.UserApplySell,
                        msg = $"用户申请成为卖家，联系人手机号{telephone}，公司名称{company_name}，联系人{contact_name}",
                        msg_title = "用户申请成为卖家",
                        msg_url = $"/account/sellerapplylist"
                    });
                    return new Tuple<bool, string>(true, "");
                }
                else
                    return new Tuple<bool, string>(false, stroutput);
            }
        }

        /// <summary>
        /// 获取卖家信息
        /// </summary>
        /// <param name="uid"></param>
        /// <returns></returns>
        public Tuple<bool, ADZ_SellerApply> GetSellerInfo(long uid)
        {
            if (uid > 0)
            {
                ADZ_MasterEntities dbcontext = new ADZ_MasterEntities();
                ADZ_SellerApply seller = dbcontext.ADZ_SellerApply.FirstOrDefault(t => t.uid == uid);
                if (seller != null)
                    return new Tuple<bool, ADZ_SellerApply>(true, seller);
                else
                    return new Tuple<bool, ADZ_SellerApply>(false, null);
            }
            return new Tuple<bool, ADZ_SellerApply>(false, null);
        }

        /// <summary>
        /// 获取账户默认头像
        /// </summary>
        /// <param name="sex"></param>
        /// <returns></returns>
        private string GetHeadUrl(int sex)
        {
            string headurl = string.Empty;
            switch (sex)
            {
                case 1:
                    headurl = ConfigHelper.AppSetting<string>("manHeadUrl");
                    break;
                case 2:
                    headurl = ConfigHelper.AppSetting<string>("womanHeadUrl");
                    break;
                default:
                    headurl = ConfigHelper.AppSetting<string>("headUrl");
                    break;
            }
            return headurl;
        }

        /// <summary>
        /// 获取用户基本信息
        /// </summary>
        /// <param name="uid"></param>
        /// <returns></returns>
        public Tuple<bool, MemberModel> GetInfo(long uid)
        {
            if (uid <= 0)
                return new Tuple<bool, MemberModel>(false, null);

            AccountInfo acc = AccountDataAccess.Instance.GetAccount(uid);
            if (acc != null)
            {
                decimal saleAmt = 0;
                decimal buyAmt = 0;
                decimal? sumSaleAmt = 0;
                decimal? sumBuyAmt = 0;
                decimal? sumRecommendAmt = 0;
                int issetpaypwd = 0;
                if (!string.IsNullOrWhiteSpace(acc.pay_password))
                    issetpaypwd = 1;

                DataTable dt = OrderBiz.Instance.GetSaleAmt(uid, DateTime.Now, DateTime.Now.AddDays(1));
                if (dt != null && dt.Rows.Count > 0)
                {
                    saleAmt = ConvertHelper.ConvertTo<decimal>(dt.Rows[0]["saleAmt"]);
                    buyAmt = ConvertHelper.ConvertTo<decimal>(dt.Rows[0]["buyAmt"]);
                }

                //总销售额
                ADZ_MasterEntities dbcontext = new ADZ_MasterEntities();
                sumSaleAmt = dbcontext.ADZ_OrderSettlement.Where(t => t.uid == uid).Sum(d => (decimal?)d.total_money);
                sumBuyAmt = dbcontext.ADZ_OrderSettlement.Where(t => t.uid == uid).Sum(d => (decimal?)d.buyer_money);
                sumRecommendAmt = dbcontext.ADZ_OrderSettlement.Where(t => t.recommend_uid == uid).Sum(d => (decimal?)d.recommend_money);

                //我的订单（待付款/待收货数量）
                int waitpayorder_num = 0;
                int paysucc_order_num = 0;
                List<OrderCount> orderlist = OrderDataAccess.Instance.GetOrderCountByStatus(uid);
                if (orderlist != null && orderlist.Count > 0)
                {
                    foreach (var item in orderlist)
                    {
                        if (item.status == (int)OrderStatus.WaitPay)
                            waitpayorder_num = item.num;
                        else if (item.status == (int)OrderStatus.PaySucc)
                            paysucc_order_num = item.num;
                    }
                }

                //我的预定（预定中/待付款数量）
                int placeing_num = 0;
                int waitpayplace_num = 0;
                List<OrderCount> placelist = OrderDataAccess.Instance.GetPlaceCountByStatus(uid);
                if (placelist != null && placelist.Count > 0)
                {
                    foreach (var item in placelist)
                    {
                        if (item.status == (int)PlaceStatus.Placeing)
                            placeing_num = item.num;
                        else if (item.status == (int)PlaceStatus.WaitPay)
                            waitpayplace_num = item.num;
                    }
                }

                int jingjiazhong_num = 0;
                int jingjiachengjiao_num = 0;
                var submit = dbcontext.ADZ_JingjiaSubmit.Where(t => t.uid == uid && t.is_del == 0);
                var master = dbcontext.ADZ_JingjiaMaster.Where(t => t.is_del == 0);
                var jingjiazhong = from sub in submit.Where(t => t.is_hit == 0)
                                   join mas in master.Where(t => t.jingjia_satus == 1)
                                   on sub.jingjia_id equals mas.jingjia_id
                                   select new
                                   {
                                       mas.jingjia_id
                                   };
                jingjiazhong_num = jingjiazhong.Count();
                var jingjiachengjiao = from sub in submit.Where(t => t.is_hit == 1 && t.order_master_id > 0 && t.status == 2)
                                       select new
                                       {
                                           sub.seq_id
                                       };
                jingjiachengjiao_num = jingjiachengjiao.Count();


                //头像处理
                string headurl = string.Empty;
                if (string.IsNullOrEmpty(acc.logo_img_url))
                    headurl = GetHeadUrl(acc.sex);
                else
                    headurl = acc.logo_img_url;

                //推荐人
                var result = GetRecommend(uid, dbcontext);

                MemberModel model = new MemberModel();
                model.uid = acc.uid;
                model.replacebuyerno = acc.replace_buyer_NO;
                model.mobile = acc.account_mobile;
                model.membername = acc.member_name;
                model.memberLevel = acc.member_level;
                model.headerUrl = headurl;
                model.balance = acc.account_balance;
                model.saleAmt = saleAmt;
                model.recommendAmt = OrderBiz.Instance.GetRecommendAmt(uid, DateTime.Now, DateTime.Now.AddDays(1));//推荐费
                model.buyAmt = buyAmt;
                model.buyer_rate = acc.buyer_rate;
                model.recommend_rate = acc.recommend_rate;
                model.add_rate = acc.add_rate;
                model.member_level_name = acc.member_level_name;
                model.waitpayorder_num = waitpayorder_num;
                model.paysucc_order_num = paysucc_order_num;
                model.waitpayplace_num = waitpayplace_num;
                model.placeing_num = placeing_num;
                model.sumsaleamt = sumSaleAmt == null ? 0 : sumSaleAmt;
                model.sumBuyAmt = sumBuyAmt == null ? 0 : sumBuyAmt;
                model.sumRecommendAmt = sumRecommendAmt == null ? 0 : sumRecommendAmt;
                model.issetpaypwd = issetpaypwd;
                model.levelList = GetMemberLevel(acc.member_level);
                model.cancashamt = acc.account_balance - acc.give_balance;
                if (model.cancashamt < 0)
                    model.cancashamt = 0;
                model.jingjiachengjiao_num = jingjiachengjiao_num;
                model.jingjiazhong_num = jingjiazhong_num;
                model.recommend = result.Item2;
                model.recommendMobile = result.Item3;

                if (dbcontext.ADZ_MemberFollow.FirstOrDefault(t => t.uid == uid) != null)
                {
                    model.isfollowed = 1;
                }
                else
                {
                    model.isfollowed = 0;
                }

                return new Tuple<bool, MemberModel>(true, model);
            }
            else
                return new Tuple<bool, MemberModel>(false, null);
        }

        /// <summary>
        /// 获取用户推荐人和手机号
        /// </summary>
        /// <param name="uid"></param>
        /// <returns></returns>
        public Tuple<bool, string, string> GetRecommend(long uid, ADZ_MasterEntities dbcontext)
        {
            //查找推荐人
            var invite = dbcontext.ADZ_InviteCode.FirstOrDefault(t => t.rel_uid == uid);
            if (invite != null)
            {
                var recommendUser = dbcontext.ADZ_MemberMaster.FirstOrDefault(t => t.uid == invite.uid);
                if (recommendUser != null)
                    return new Tuple<bool, string, string>(true, recommendUser.member_name, recommendUser.account_mobile);
            }
            return new Tuple<bool, string, string>(false, "", "");
        }

        /// <summary>
        /// 完善用户信息
        /// </summary>
        public Tuple<bool, string> WriteDetails(long uid, string real_name, string id_number, string contact_mobile,
            string company_name, string company_address, string company_telephone, int customer_type)
        {
            if (uid > 0)
            {
                ADZ_MasterEntities dbcontext = new ADZ_MasterEntities();

                var acc = dbcontext.ADZ_MemberMaster.FirstOrDefault(t => t.uid == uid && t.is_del == 0);
                if (acc == null)
                    return new Tuple<bool, string>(false, "用户不存在");

                var info = dbcontext.ADZ_MemberDetails.FirstOrDefault(t => t.uid == uid);
                if (info != null)
                {
                    info.real_name = real_name;
                    info.id_number = id_number;
                    info.contact_mobile = contact_mobile;
                    info.company_address = company_address;
                    info.company_name = company_name;
                    info.company_telephone = company_telephone;

                    info.customer_type = customer_type;
                    info.customer_type_name = EnumHelper.GetEnumItemDescription<customer_type>(customer_type);

                    dbcontext.SaveChanges();
                }
                else
                {
                    ADZ_MemberDetails model = new ADZ_MemberDetails()
                    {
                        uid = uid,
                        company_address = company_address,
                        company_name = company_name,
                        company_telephone = company_telephone,
                        contact_mobile = contact_mobile,
                        id_number = id_number,
                        real_name = real_name,
                        create_time = DateTime.Now,
                        customer_type = customer_type
                    };
                    model.customer_type_name = EnumHelper.GetEnumItemDescription<customer_type>(customer_type);

                    dbcontext.ADZ_MemberDetails.Add(model);
                    dbcontext.SaveChanges();
                }

                return new Tuple<bool, string>(true, "");
            }
            else
                return new Tuple<bool, string>(false, "用户不存在");
        }

        /// <summary>
        /// 获取账户个人及公司信息
        /// </summary>
        /// <param name="uid"></param>
        /// <returns></returns>
        public Tuple<bool, MemberDetailsModel> GetDetails(long uid)
        {
            if (uid > 0)
            {
                ADZ_MasterEntities dbcontext = new ADZ_MasterEntities();
                var info = dbcontext.ADZ_MemberDetails.FirstOrDefault(t => t.uid == uid);
                if (info != null)
                {
                    MemberDetailsModel model = new MemberDetailsModel()
                    {
                        uid = info.uid,
                        address = info.address,
                        company_address = info.company_address,
                        company_name = info.company_name,
                        company_telephone = info.company_telephone,
                        contact_mobile = info.contact_mobile,
                        id_number = info.id_number,
                        real_name = info.real_name,
                        customer_type = info.customer_type.HasValue ? info.customer_type.Value : 0
                    };
                    return new Tuple<bool, MemberDetailsModel>(true, model);
                }
                else
                    return new Tuple<bool, MemberDetailsModel>(false, null);
            }
            else
                return new Tuple<bool, MemberDetailsModel>(false, null);
        }

        /// <summary>
        /// 设置用户昵称
        /// </summary>
        public Tuple<bool, string> EditNick(long uid, string nickname)
        {
            ADZ_MasterEntities dbcontext = new ADZ_MasterEntities();
            var acc = dbcontext.ADZ_MemberMaster.FirstOrDefault(t => t.uid == uid && t.is_del == 0);
            if (acc == null)
                return new Tuple<bool, string>(false, "用户不存在");

            if (acc.member_name == nickname)
                return new Tuple<bool, string>(false, "用户昵称不需要修改");

            acc.member_name = nickname;
            dbcontext.SaveChanges();
            return new Tuple<bool, string>(true, "");
        }

        /// <summary>
        /// 设置头像
        /// </summary>
        public Tuple<bool, string> EditHeader(long uid, string headerdata, string filetype)
        {
            ADZ_MasterEntities dbcontext = new ADZ_MasterEntities();
            var acc = dbcontext.ADZ_MemberMaster.FirstOrDefault(t => t.uid == uid && t.is_del == 0);
            if (acc == null)
                return new Tuple<bool, string>(false, "用户不存在");

            var result = ImageFileBiz.UpImg(headerdata, filetype, "headimg");
            if (!result.Item1)
                return new Tuple<bool, string>(false, result.Item2);

            acc.logo_img_url = AliyunOssBiz.GetImg(result.Item3);
            dbcontext.SaveChanges();
            return new Tuple<bool, string>(true, "");
        }

        /// <summary>
        /// 获取账户会员等级
        /// </summary>
        /// <param name="uid"></param>
        /// <returns></returns>
        public Tuple<bool, short> GetMemberLevel(long uid)
        {
            if (uid > 0)
            {
                AccountInfo acc = AccountDataAccess.Instance.GetAccount(uid);
                if (acc != null)
                    return new Tuple<bool, short>(true, acc.member_level);
                else
                    return new Tuple<bool, short>(false, 0);
            }
            else
                return new Tuple<bool, short>(false, 0);
        }

        /// <summary>
        /// 我的账单
        /// </summary>
        /// <returns></returns>
        public Tuple<bool, BillModel> GetBill(long uid, int orderType, int pageIndex, int pageRows)
        {
            if (uid <= 0)
                return new Tuple<bool, BillModel>(false, null);

            DataSet ds = AccountDataAccess.Instance.GetAmountLogList(uid, orderType, pageIndex, pageRows);
            if (ds != null && ds.Tables.Count > 0 && ds.Tables[1].Rows.Count > 0)
            {
                BillModel model = new BillModel();
                model.list = new ModelHandler<AmountLogModel>().FillModel(ds.Tables[1]);
                model.allrows = ConvertHelper.ConvertTo<int>(ds.Tables[0].Rows[0]["allrows"]);
                model.allpages = ConvertHelper.ConvertTo<int>(ds.Tables[0].Rows[0]["allpages"]);

                return new Tuple<bool, BillModel>(true, model);
            }
            else
                return new Tuple<bool, BillModel>(false, null);

        }

        /// <summary>
        /// 设置支付密码
        /// </summary>
        /// <returns></returns>
        public Tuple<bool, string> SetPayPwd(long uid, string paypwd, string code)
        {
            if (uid <= 0)
                return new Tuple<bool, string>(false, "用户不存在");

            var acc = AccountDataAccess.Instance.GetAccount(uid);
            if (acc == null)
                return new Tuple<bool, string>(false, "用户不存在");

            var result = CheckCode(acc.account_mobile, code, (int)SendType.PayPwdCode);
            if (!result.Item1)
                return new Tuple<bool, string>(false, result.Item2);

            string stroutput = string.Empty;
            paypwd = Utils.Md5Encrypt(paypwd + ".adz", Encoding.UTF8);
            int ret = AccountDataAccess.Instance.SetPayPwd(uid, paypwd, out stroutput);
            if (ret > 0)
                return new Tuple<bool, string>(true, "");
            else
                return new Tuple<bool, string>(false, stroutput);
        }

        /// <summary>
        /// 检查支付密码是否正常
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="paypwd"></param>
        /// <param name="checkpaypwd"></param>
        /// <returns></returns>
        public Tuple<bool, string> CheckPayPwd(long uid, string paypwd, string checkpaypwd)
        {
            //判断支付密码
            string paypwdErrorKey = string.Format("paypwd-error-{0}-{1}", uid, paypwd);    //支付密码错误次数
            int errorNum = RedisService.Get<int>(paypwdErrorKey);
            if (errorNum >= 4)
            {
                //支付密码错误5次，不允许用户在支付，防止刷支付密码
                LogHelper.Error("支付交易订单,支付密码已错误5次");
                return new Tuple<bool, string>(false, "支付密码已错误5次");
            }

            checkpaypwd = Utils.Md5Encrypt(checkpaypwd + ".adz", Encoding.UTF8);
            if (!paypwd.Equals(checkpaypwd))
            {
                if (errorNum == 0)
                    RedisService.Set(paypwdErrorKey, 1, DateTime.Now.AddDays(1));
                else
                    RedisService.Set(paypwdErrorKey, errorNum + 1, DateTime.Now.AddDays(1));
                return new Tuple<bool, string>(false, "支付密码不正确");
            }
            return new Tuple<bool, string>(true, "");
        }


        /// <summary>
        /// 填写发票
        /// </summary>
        /// <returns></returns>
        public Tuple<bool, string> WriteInvoice(long id, long uid, int invoice_type, string invoice_title, string invoice_content, string taxpayer_ID)
        {
            if (uid <= 0)
                return new Tuple<bool, string>(false, "用户不存在");

            string stroutput = string.Empty;
            long ret = AccountDataAccess.Instance.WriteInvoice(id, uid, invoice_type, invoice_title, invoice_content, taxpayer_ID, out stroutput);
            if (ret > 0)
                return new Tuple<bool, string>(true, ret.ToString());
            else
                return new Tuple<bool, string>(false, stroutput);
        }


        /// <summary>
        /// 获取用户发票
        /// </summary>
        /// <param name="uid"></param>
        /// <returns></returns>
        public Tuple<bool, List<AccountInvoice>, string> GetInvoice(long uid)
        {
            if (uid <= 0)
                return new Tuple<bool, List<AccountInvoice>, string>(false, null, "用户不存在");

            List<AccountInvoice> list = AccountDataAccess.Instance.GetInvoice(uid);
            if (list != null)
                return new Tuple<bool, List<AccountInvoice>, string>(true, list, "");
            else
                return new Tuple<bool, List<AccountInvoice>, string>(false, null, "用户发票为空");
        }

        /// <summary>
        /// 提现银行
        /// </summary>
        /// <returns></returns>
        public Tuple<bool, string, long> EditCashBank(long uid, int bank_id, string bank_account, string branch_bank_name, string bank_account_name, string code)
        {
            if (uid <= 0)
                return new Tuple<bool, string, long>(false, "用户不存在", 0);

            var acc = AccountDataAccess.Instance.GetAccount(uid);
            if (acc == null)
                return new Tuple<bool, string, long>(false, "用户不存在", 0);

            var result = CheckCode(acc.account_mobile, code, (int)SendType.XiugaiTixianYinhang);
            if (!result.Item1)
                return new Tuple<bool, string, long>(false, result.Item2, 0);

            if (uid <= 0 || bank_id <= 0 || string.IsNullOrEmpty(bank_account) || string.IsNullOrEmpty(branch_bank_name) || string.IsNullOrEmpty(bank_account_name))
                return new Tuple<bool, string, long>(false, "提现失败，参数错误", 0);

            string stroutput = string.Empty;
            var ret = AccountDataAccess.Instance.EditCashBank(uid, bank_id, bank_account, branch_bank_name, bank_account_name, out stroutput);
            if (ret > 0)
                return new Tuple<bool, string, long>(true, "", ret);
            else
                return new Tuple<bool, string, long>(false, stroutput, 0);
        }

        /// <summary>
        /// 获取用户提现银行
        /// </summary>
        public Tuple<bool, CashBankModel> GetCashBank(long uid)
        {
            ADZ_MasterEntities dbcontext = new ADZ_MasterEntities();
            CashBankModel cashBankModel = new CashBankModel();
            var queryModel = dbcontext.ADZ_MemberCashBank.FirstOrDefault(t => t.uid == uid);
            if (queryModel != null)
            {
                List<string> exclist = new List<string>();
                exclist.Add("seq_id");
                exclist.Add("mobile");
                Utils.Mapper<CashBankModel, ADZ_MemberCashBank>(cashBankModel, queryModel, exclist);
                cashBankModel.cash_bank_id = queryModel.seq_id;
                return new Tuple<bool, CashBankModel>(true, cashBankModel);
            }
            else
                return new Tuple<bool, CashBankModel>(false, null);
        }

        public string GetCityName(string cityid)
        {
            string city_name = "";
            ADZ_MasterEntities dbcontext = new ADZ_MasterEntities();
            if (cityid == null || cityid.Length < 6)
            {
                cityid = (cityid + "000000").Substring(0, 6);
            }
            if (cityid.Length >= 6)
            {
                try
                {
                    string first_id = cityid.Substring(0, 2) + "0000";
                    string second_id = cityid.Substring(0, 4) + "00";
                    string third_id = cityid.Substring(0, 6);
                    city_name = string.Format("{0} {1} {2}",
                    dbcontext.ADZ_City.FirstOrDefault(t => t.CityId == first_id).CityName,
                    dbcontext.ADZ_City.FirstOrDefault(t => t.CityId == second_id).CityName,
                    dbcontext.ADZ_City.FirstOrDefault(t => t.CityId == third_id).CityName);
                }
                catch
                {
                    return city_name;
                }
            }
            return city_name;
        }

        #endregion

        #region 收货地址
        /// <summary>
        /// 新增收货地址
        /// </summary>
        /// <param name="uid">用户userid</param>
        /// <param name="consignee">收货人</param>
        /// <param name="mobile">收货手机号</param>
        /// <param name="address">详细地址</param>
        /// <param name="isDefault">是否默认 0 否 1 是</param>
        /// <returns></returns>
        public Tuple<bool, long, string> AddAddress(long uid, string cityid, string cityname, string address, string receiver, string telephone, int isDefault)
        {
            if (uid <= 0)
                return new Tuple<bool, long, string>(false, 0, "用户不存在");

            string stroutput = string.Empty;
            long ret = AccountDataAccess.Instance.AddAddress(uid, cityid, cityname, address, receiver, telephone, isDefault, out stroutput);
            if (ret > 0)
                return new Tuple<bool, long, string>(true, ret, "");
            else
                return new Tuple<bool, long, string>(false, 0, stroutput);
        }

        /// <summary>
        /// 编辑收货地址
        /// </summary>
        /// <param name="id"></param>
        /// <param name="consignee">收货人</param>
        /// <param name="mobile">收货手机号</param>
        /// <param name="address">详细地址</param>
        /// <param name="isDefault">是否默认 0 否 1 是</param>
        /// <returns></returns>
        public Tuple<bool, string> EditAddress(long id, long uid, string cityid, string cityname, string address, string receiver, string telephone, int isDefault)
        {
            if (uid <= 0)
                return new Tuple<bool, string>(false, "用户不存在");

            string stroutput = string.Empty;
            long ret = AccountDataAccess.Instance.EditAddress(id, uid, cityid, cityname, address, receiver, telephone, isDefault, out stroutput);
            if (ret > 0)
                return new Tuple<bool, string>(true, "");
            else
                return new Tuple<bool, string>(false, stroutput);
        }

        /// <summary>
        /// 删除收货地址
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Tuple<bool, long, string> DelAddress(long id, long uid)
        {
            string stroutput = string.Empty;
            long new_seq_id = 0;
            if (AccountDataAccess.Instance.DelAddress(id, uid, out new_seq_id, out stroutput) > 0)
                return new Tuple<bool, long, string>(true, new_seq_id, "");
            else
                return new Tuple<bool, long, string>(false, 0, stroutput);
        }

        /// <summary>
        /// 获取用户所有收货地址
        /// </summary>
        /// <param name="uid"></param>
        /// <returns></returns>
        public Tuple<bool, List<AddressInfo>> GetAddressList(long uid)
        {
            DataSet ds = AccountDataAccess.Instance.GetAddressList(uid);
            if (ds != null && ds.Tables[0] != null && ds.Tables[0].Rows.Count > 0)
            {
                List<AddressInfo> list = new ModelHandler<AddressInfo>().FillModel(ds);
                if (list != null)
                    return new Tuple<bool, List<AddressInfo>>(true, list);
                else
                    return new Tuple<bool, List<AddressInfo>>(false, null);
            }
            else
                return new Tuple<bool, List<AddressInfo>>(false, null);
        }

        /// <summary>
        /// 获取收货地址
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public AddressInfo GetAddress(long id)
        {
            return AccountDataAccess.Instance.GetAddress(id);
        }
        #endregion

        #region 账户充值
        /// <summary>
        /// 账户充值
        /// </summary>
        /// <returns></returns>
        public Tuple<bool, string, string> Charge(long uid, decimal amt, int channelType)
        {
            string strouput = string.Empty;
            //1.验证账户
            AccountInfo info = AccountDataAccess.Instance.GetAccount(uid);
            if (info == null)
                return new Tuple<bool, string, string>(false, "", "用户不存在");

            //验证用户状态
            if (info.account_status != (short)AccountStatus.Normal)
            {
                LogHelper.Error("用户禁止登录");
                return new Tuple<bool, string, string>(false, "", "用户异常");
            }

            //2.创建充值订单
            string orderId = Utils.BuildOrderId("CH", 20);
            string remark = string.Empty;
            //下家订单号（支付宝/微信），下家不同订单号规则可能不同
            string billNo = string.Empty;
            switch (channelType)
            {
                case (int)ChannelType.AlipayApp:
                    billNo = Utils.BuildOrderId("", 20);
                    remark = "支付宝app充值";
                    break;
                case (int)ChannelType.WechatApp:
                    billNo = Utils.BuildOrderId("", 20);
                    remark = "微信app充值";
                    break;
                default:
                    billNo = Utils.BuildOrderId("", 20);
                    break;
            }
            bool flag = OrderBiz.Instance.CreateChargeOrder(orderId, billNo, uid, 0, 0, amt, channelType, remark);
            if (!flag)
                return new Tuple<bool, string, string>(false, "", "创建充值订单失败");


            //3.开始提交下家充值（支付宝/微信/银联等）
            Tuple<bool, string, string> result = new Tuple<bool, string, string>(true, "", "");
            switch (channelType)
            {
                case (int)ChannelType.AlipayApp:
                    result = AlipayBiz.DoSubmit(billNo, amt);
                    break;
                case (int)ChannelType.WechatApp:
                    result = WechatBiz.BuildOrder(billNo, amt);
                    break;
            }

            if (result.Item1)
            {
                ChargeRespModel model = new ChargeRespModel();
                model.orderId = orderId;
                model.channelType = channelType;
                model.respData = result.Item2;
                return new Tuple<bool, string, string>(true, JsonHelper.Serialize(model), "");
            }
            else
            {
                //调用支付宝or微信充值失败
                OrderDataAccess.Instance.ChargeOrderFail(orderId, "", result.Item3, out strouput);
                return new Tuple<bool, string, string>(false, "", result.Item3);
            }

        }
        #endregion

        #region 我的关注
        /// <summary>
        /// 新增or取消关注
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="op_type"></param>
        /// <param name="follow_type"></param>
        /// <param name="follow_id"></param>
        /// <returns></returns>
        public Tuple<bool, string> HandleFollow(long uid, int op_type, int follow_type, long follow_id)
        {
            string stroutput = string.Empty;
            long ret = AccountDataAccess.Instance.HandleFollow(uid, op_type, follow_type, follow_id, out stroutput);
            if (ret > 0)
                return new Tuple<bool, string>(true, "");
            else
                return new Tuple<bool, string>(false, stroutput);
        }

        /// <summary>
        /// 我的关注
        /// </summary>
        public FollowListModel GetFollow(long uid, int follow_type)
        {
            FollowListModel model = new FollowListModel();
            DataTable dt = AccountDataAccess.Instance.GetFollow(uid, follow_type);
            if (dt != null && dt.Rows.Count > 0)
            {
                model.list = new ModelHandler<FollowModel>().FillModel(dt, false, false);

                //处理图片
                if (follow_type == (int)FollowType.Brand)
                {
                    foreach (var item in model.list)
                    {
                        string logimgurl = item.img_url.ToLower();
                        if (!string.IsNullOrWhiteSpace(logimgurl) && !(logimgurl.StartsWith("http://") || logimgurl.StartsWith("https://")))
                            item.img_url = AliyunOssBiz.GetImg(logimgurl);
                    }
                }
            }
            return model;
        }
        #endregion

        #region 注册奖励
        /// <summary>
        /// 注册奖励随机算法
        /// </summary>
        /// <returns></returns>
        private decimal GetRegisterReward()
        {
            decimal money = 0;
            //1. 随机产生1-100之间随机数
            Random rand = new Random(Guid.NewGuid().GetHashCode());
            int numRand = rand.Next(1, 100);

            //2. 读取奖励配置
            string jsonFile = System.Web.HttpContext.Current.Server.MapPath("~/Config/RegisterReward.json");
            List<RegisterRewardContext> list = JsonHelper.DeserializeFileList<RegisterRewardContext>(jsonFile);
            if (list != null && list.Count != 0)
            {
                foreach (var item in list)
                {
                    if (numRand >= item.start && numRand <= item.end)
                    {
                        if (item.start_money == item.end_money)
                            money = item.start_money;
                        else
                        {
                            //注册奖励金额属于区间范围,再次区间内随机下金额
                            money = rand.Next(item.start_money, item.end_money);
                        }
                    }
                }
            }

            if (money != 0)
                money += 0.8M;
            else
                LogHelper.Error("读取注册奖励json配置失败");
            return money;
        }
        #endregion


    }
}
